package com.example.service;

import com.example.entity.Booking;
import com.example.entity.Room;
import com.example.exception.CustomException;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 房间分配服务
 */
@Service
public class RoomAllocationService {

    @Resource
    private RoomService roomService;
    
    @Resource
    private RoomAvailabilityService roomAvailabilityService;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    
    /**
     * 为预订分配最合适的房间
     * @param booking 预订信息
     * @return 分配的房间
     */
    @Transactional
    public Room allocateRoom(Booking booking) {
        if (booking == null || booking.getHotelId() == null) {
            throw new CustomException("400", "预订信息不完整");
        }
        
        // 获取入住和退房日期
        LocalDate checkInDate = LocalDate.parse(booking.getCheckInDate(), DATE_FORMATTER);
        LocalDate checkOutDate = LocalDate.parse(booking.getCheckOutDate(), DATE_FORMATTER);
        
        // 检查日期是否合法
        if (checkInDate.isAfter(checkOutDate) || checkInDate.isEqual(checkOutDate)) {
            throw new CustomException("400", "入住日期必须早于退房日期");
        }
        
        // 获取酒店下所有可用房间
        List<Room> availableRooms = getAvailableRooms(booking.getHotelId(), checkInDate, checkOutDate);
        
        // 筛选同类型的房间
        if (booking.getRoomId() != null) {
            // 如果指定了房间ID，优先匹配该房间
            Room targetRoom = availableRooms.stream()
                    .filter(room -> room.getId().equals(booking.getRoomId()))
                    .findFirst()
                    .orElse(null);
            
            if (targetRoom != null) {
                // 如果指定房间可用，直接分配
                return allocateSpecificRoom(booking, targetRoom);
            }
            
            // 指定房间不可用，尝试匹配相同类型的房间
            Room originalRoom = roomService.selectById(booking.getRoomId());
            if (originalRoom != null) {
                List<Room> sameTypeRooms = availableRooms.stream()
                        .filter(room -> room.getRoomType().equals(originalRoom.getRoomType()))
                        .collect(Collectors.toList());
                
                if (!sameTypeRooms.isEmpty()) {
                    // 分配同类型房间中最适合的一个
                    Room bestMatchRoom = findBestMatchRoom(sameTypeRooms);
                    return allocateSpecificRoom(booking, bestMatchRoom);
                }
            }
        }
        
        // 如果没有指定房间或找不到合适的同类型房间，按算法选择最合适的房间
        if (availableRooms.isEmpty()) {
            throw new CustomException("404", "该时间段内没有可用房间");
        }
        
        Room bestRoom = findBestMatchRoom(availableRooms);
        return allocateSpecificRoom(booking, bestRoom);
    }
    
    /**
     * 获取指定日期范围内的可用房间
     */
    public List<Room> getAvailableRooms(Long hotelId, LocalDate checkInDate, LocalDate checkOutDate) {
        // 获取酒店所有房间
        List<Room> hotelRooms = roomService.selectByHotelId(hotelId);
        
        // 过滤出可用房间（剩余数量>0）
        List<Room> availableRooms = hotelRooms.stream()
                .filter(room -> room.getQuantity() > 0)
                .collect(Collectors.toList());
        
        // 排除已预订的房间
        List<Room> finalAvailableRooms = new ArrayList<>();
        for (Room room : availableRooms) {
            boolean isAvailable = roomAvailabilityService.checkRoomAvailability(
                    room.getId(),
                    checkInDate.format(DATE_FORMATTER),
                    checkOutDate.format(DATE_FORMATTER)
            );
            
            if (isAvailable) {
                finalAvailableRooms.add(room);
            }
        }
        
        return finalAvailableRooms;
    }
    
    /**
     * 在可用房间中找到最佳匹配的房间
     * 优先考虑高总价值（价格*数量）的房间，避免浪费高价值资源
     */
    private Room findBestMatchRoom(List<Room> availableRooms) {
        // 根据价格和数量计算房间的总价值，选择价值量最大的房间
        return availableRooms.stream()
                .sorted(Comparator.comparing(room -> {
                    // 计算房间的总价值（价格*数量）
                    return room.getPrice().multiply(java.math.BigDecimal.valueOf(room.getQuantity()));
                }))
                .findFirst()
                .orElse(availableRooms.get(0));  // 默认取列表第一个
    }
    
    /**
     * 分配特定房间
     */
    @Transactional
    public Room allocateSpecificRoom(Booking booking, Room room) {
        if (room == null) {
            throw new CustomException("404", "指定房间不存在或不可用");
        }
        
        // 更新预订信息
        booking.setRoomId(room.getId());
        
        // 减少可用数量
        if (room.getQuantity() > 0) {
            room.setQuantity(room.getQuantity() - 1);
            roomService.update(room);
        } else {
            throw new CustomException("400", "房间已无可用数量");
        }
        
        return room;
    }
} 